/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin		 	*/
/*	Project:	GlbLib-1.0.0			*/
/*	Author:		gong_libin			*/
/*	Date:		2016_06_01			*/
/*	Bloom:		GlbUtil.cpp			*/
/********************************************************/

#include "GlbUtil.h"

void GlbLocalDay(char* pszDay)
{
	time_t ulTime;
	struct tm* pstTime = NULL;

	ulTime = time(NULL);
	pstTime = localtime(&ulTime);
	strftime(pszDay, GLB_DAYTIME, "%Y-%m-%d", pstTime);

	return;
}

void GlbLocalTime(char* pszTime)
{
	time_t ulTime;
	struct tm* pstTime = NULL;

	ulTime = time(NULL);
	pstTime = localtime(&ulTime);
	strftime(pszTime, GLB_DAYTIME, "%H:%M:%S", pstTime);

	return;
}

void GlbLocalDayTime(char* pszDayTime)
{
	time_t ulTime;
	struct tm* pstTime = NULL;

	ulTime = time(NULL);
	pstTime = localtime(&ulTime);
	strftime(pszDayTime, GLB_DAYTIME, "%Y-%m-%d %H:%M:%S", pstTime);

	return;
}

char* GlbLocalPath(char* pszEnv)
{
	return getenv(pszEnv);
}

void GlbReset(void* pReset, ULONG ulSize)
{
	if (NULL != pReset) {
		memset(pReset, '\0', sizeof(UCHAR) * ulSize);
	}

	return;
}

void* GlbMalloc(ULONG ulSize)
{
	void* pReturn = NULL;

	if (NULL != (pReturn = malloc(sizeof(UCHAR) * ulSize))) {
		memset(pReturn, '\0', sizeof(UCHAR) * ulSize);
	}
	else {
		GLB_ERROR("%s\n", strerror(errno));
	}

	return pReturn;
}

void GlbFree(void** ppFree)
{
	if (NULL != *ppFree) {
		free(*ppFree);
		*ppFree = NULL;
	}

	return;
}

void GlbFork()
{
	switch (fork()) {
		case GLB_SUCCESS:
			umask(0);
			setsid();
			chdir("/");
			break;
		case GLB_FAILURE:
			GLB_ERROR("%s\n", strerror(errno));
			break;
		default:
			sleep(1);
			exit(GLB_SUCCESS);
			break;
	}

	return;
}

void GlbPacketDisplay(UCHAR* puszPacket, int iLength)
{
	int iCount = 0;

	GLB_PRINT("Packet[%d]:", iLength);
	for (; iCount < iLength; iCount ++) {
		if (0 == iCount % sizeof(int)) {
			if (0 == iCount % (sizeof(int) * 2)) {
				GLB_PRINT("\n");
			}
			else {
				GLB_PRINT(" ");
			}
		}
		GLB_PRINT("0x%02x ", *(puszPacket + iCount));
	}
	GLB_PRINT("\n");

	return;
}

UCHAR* GlbBaseEncode(UCHAR* puszSrc, int iSrc, int* piDst)
{
	int iDst = 0;
	UCHAR *puszIn = NULL;
	UCHAR *puszEnd = NULL;
	UCHAR *puszDst = NULL;
	UCHAR *puszPos = NULL;
	UCHAR uszBase[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

	iDst = (iSrc + 3 - iSrc % 3) * 4 / 3 + 1;
	if (NULL != (puszDst = (UCHAR*)GlbMalloc(sizeof(UCHAR) * iDst))) {
		puszIn = puszSrc;
		puszEnd = puszSrc + iSrc;
		puszPos = puszDst;

		while (puszEnd - puszIn >= 3) {
			*puszPos ++ = uszBase[puszIn[0] >> 2];
			*puszPos ++ = uszBase[((puszIn[0] & 0x03) << 4) | (puszIn[1] >> 4)];
			*puszPos ++ = uszBase[((puszIn[1] & 0x0f) << 2) | (puszIn[2] >> 6)];
			*puszPos ++ = uszBase[puszIn[2] & 0x3f];
			puszIn += 3;
		}

		if (puszEnd - puszIn) {
			*puszPos ++ = uszBase[puszIn[0] >> 2];
			if (puszEnd - puszIn == 1) {
				*puszPos ++ = uszBase[(puszIn[0] & 0x03) << 4];
				*puszPos ++ = '=';
			}
			else {
				*puszPos ++ = uszBase[((puszIn[0] & 0x03) << 4) | (puszIn[1] >> 4)];
				*puszPos ++ = uszBase[(puszIn[1] & 0x0f) << 2];
			}
			*puszPos ++ = '=';
		}

		*piDst = puszPos - puszDst;
		*puszPos = '\0';
	}

	return puszDst;
}

UCHAR* GlbBaseDecode(UCHAR* puszSrc, int iSrc, int* piDst)
{
	int iCnt = 0;
	int iDst = 0;
	int iCount = 0;
	UCHAR ucTmp = '\0';
	UCHAR *puszDst = NULL;
	UCHAR *puszPos = NULL;
	UCHAR uszIn[4] = { 0 };
	UCHAR uszBlock[4] = { 0 };
	UCHAR uszTable[256] = { 0x80 };
	UCHAR uszBase[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

	for (iCnt = 0; iCnt < sizeof(uszBase) - 1; iCnt ++) {
		uszTable[uszBase[iCnt]] = (UCHAR)iCnt;
	}
	uszTable['='] = 0;

	for (iCnt = 0; iCnt < iSrc; iCnt ++) {
		if (0x80 != uszTable[puszSrc[iCnt]]) {
			iCount ++;
		}
	}

	if (0 == iCount % 4) {
		iDst = iCount / 4 * 3;
		if (NULL != (puszPos = puszDst = (UCHAR*)GlbMalloc(sizeof(UCHAR) * iDst))) {
			iCount = 0;
			for (iCnt = 0; iCnt < iSrc; iCnt ++) {
				if (0x80 == (ucTmp = uszTable[puszSrc[iCnt]])) {
					continue;
				}
		
				uszIn[iCount] = puszSrc[iCnt];
				uszBlock[iCount] = ucTmp;
				iCount ++;
				if (4 ==  iCount) {
					*puszPos ++ = (uszBlock[0] << 2) | (uszBlock[1] >> 4);
					*puszPos ++ = (uszBlock[1] << 4) | (uszBlock[2] >> 2);
					*puszPos ++ = (uszBlock[2] << 6) | uszBlock[3];
					iCount = 0;
				}
			}

			if (puszPos > puszDst) {
				if (uszIn[2] == '=') {
					puszPos -= 2;
				}
				else if (uszIn[3] == '=') {
					puszPos --;
				}
			}
			*piDst = puszPos - puszDst;
		}
	}

	return puszDst;
}

void GlbIpcShmKernel(ULONG ulMax, ULONG ulAll)
{
	char szGlbd[GLB_BYTE64] = { 0 };

	sprintf(szGlbd, "sysctl -w kernel.shmmax=%ld", ulMax);
	system(szGlbd);

	memset(szGlbd, '\0', GLB_BYTE64);
	sprintf(szGlbd, "sysctl -w kernel.shmall=%ld", ulAll);
	system(szGlbd);

	return;
}

void GlbIpcMsgKernel(ULONG ulMax, ULONG ulMnb, ULONG ulMni)
{
	char szGlbd[GLB_BYTE64] = { 0 };

	sprintf(szGlbd, "sysctl -w kernel.msgmax=%ld", ulMax);
	system(szGlbd);

	memset(szGlbd, '\0', GLB_BYTE64);
	sprintf(szGlbd, "sysctl -w kernel.msgmnb=%ld", ulMnb);
	system(szGlbd);

	memset(szGlbd, '\0', GLB_BYTE64);
	sprintf(szGlbd, "sysctl -w kernel.msgmni=%ld", ulMni);
	system(szGlbd);

	return;
}

int GlbCoreDump(int iType)
{
	 struct rlimit stLimit = {0, 0};

	 if (GLB_SUCCESS == getrlimit(RLIMIT_CORE, &stLimit)) {
		stLimit.rlim_cur = iType;
	}

	return setrlimit(RLIMIT_CORE, &stLimit);
}

int GlbMaxFileGet()
{
	int iNum = 0;
	struct rlimit stLimit = {0, 0};

	if (GLB_SUCCESS == getrlimit(RLIMIT_NOFILE, &stLimit)) {
		iNum = stLimit.rlim_cur;
	}

	return iNum;
}

int GetMaxFileSet(int iNum)
{
	struct rlimit stLimit = {0, 0};

	if (GLB_SUCCESS == getrlimit(RLIMIT_NOFILE, &stLimit)) {
		stLimit.rlim_cur = iNum;
	}

	return setrlimit(RLIMIT_NOFILE, &stLimit);
}

void GlbKeyCode(int iFlag, char* pszKey, char* pszSrc, char* pszDst)
{
	int iCur = 0;
	int iSrc = strlen(pszSrc);
	int iKey = iSrc % GLB_KSIZE;

	for (; iCur < iSrc; iCur ++) {
		switch (iFlag) {
			case GLB_KENCD:
				*(pszDst + iCur) = *(pszSrc + iCur) - *(pszKey + iKey);
				break;
			case GLB_KDECD:
				*(pszDst + iCur) = *(pszSrc + iCur) + *(pszKey + iKey);
				break;
			default:
				break;
		}
		++ iKey == GLB_KSIZE ? iKey = 0 : iKey;
	}

	return;
}

char GlbUrlCodeHexFrom(char cKey)
{
	return isdigit(cKey) ? cKey - '0' : tolower(cKey) - 'a' + 10;
}

char GlbUrlCodeHexInto(char cKey)
{
	static char szHex[] = "0123456789ABCDEF";

	return szHex[cKey & 15];
}

char* GlbUrlEncode(char* pszSrc)
{
	char* pszDst = NULL;
	char* pszDstCur = NULL;
	char* pszSrcCur = pszSrc;

	if (NULL != (pszDst = pszDstCur = (char*)GlbMalloc(strlen(pszSrc) * 3 + 1))) {
		while ('\0' != *pszSrcCur) {
			if (isalnum(*pszSrcCur) || '-' == *pszSrcCur || '_' == *pszSrcCur || '=' == *pszSrcCur || '.' == *pszSrcCur || '~' == *pszSrcCur) {
				*pszDstCur ++ = *pszSrcCur;
			}
			else if (' ' == *pszSrcCur) {
				*pszDstCur ++ = '+';
			}
			else {
				*pszDstCur ++ = '%';
				*pszDstCur ++ = GlbUrlCodeHexInto(*pszSrcCur >> 4);
				*pszDstCur ++ = GlbUrlCodeHexInto(*pszSrcCur & 15);
			}
			pszSrcCur += 1;
		}
	}

	*pszDstCur = '\0';

	return pszDst;
}

char* GlbUrlDecode(char* pszSrc)
{
	char* pszDst = NULL;
	char* pszDstCur = NULL;
	char* pszSrcCur = pszSrc;

	if (NULL != (pszDst = pszDstCur = (char*)GlbMalloc(strlen(pszSrc) + 1))) {
		while ('\0' != *pszSrcCur) {
			if ('%' == *pszSrcCur) {
				if ('\0' != pszSrcCur[1] && '\0' != pszSrcCur[2]) {
					*pszDstCur ++ = GlbUrlCodeHexFrom(pszSrcCur[1]) << 4 | GlbUrlCodeHexFrom(pszSrcCur[2]);
					pszSrcCur += 2;
				}
			}
			else if ('+' == *pszSrcCur) { 
				*pszDstCur ++ = ' ';
			}
			else {
				*pszDstCur ++ = *pszSrcCur;
			}
			pszSrcCur += 1;
		}
	}

	*pszDstCur = '\0';

	return pszDst;
}
